#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "AmbientLight.h"
#include "mock/LoggerMock.h"
#include "mock/ArduinoMock.h"
#include "mock/MessageRouterMock.h"
using ::testing::Return;
using ::testing::Eq;
using ::testing::ByRef;

class AmbientLightTest : public ::testing::Test {
public:
	AmbientLightTest() : TIME_DELAY(6000), ambient(arduino, router, "test", log, "kitchen", "kitchen", "kitchen", TIME_DELAY), TIME_TICK(2) {}
protected:
	const long TIME_DELAY;
	ArduinoMock arduino;
	MessageRouterMock router;
	AmbientLight ambient;
	LoggerMock log;
	const long TIME_TICK;
	long millis;

	virtual void SetUp() {
		millis = 0;
		EXPECT_CALL(router, addService(Eq(ByRef(ambient))));
		router.addService(ambient);
	}

	// virtual void TearDown() {}
};

TEST_F(AmbientLightTest, turnOnOffWhenButtonPressed){
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}")))
		.Times(1);
	EXPECT_CALL(arduino, milliseconds()).
			Times(AnyNumber()).
			WillRepeatedly(Return(millis));
	ambient.onMessage("{\"event\":\"button\", \"id\":\"kitchen\", \"state\":\"on\"}");
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"off\"}")))
		.Times(1);
	ambient.onMessage("{\"event\":\"button\", \"id\":\"kitchen\", \"state\":\"on\"}");
}
TEST_F(AmbientLightTest, turnOnWhenMontionDetected){
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}")))
		.Times(1);
	EXPECT_CALL(arduino, milliseconds()).
			WillOnce(Return(millis));

	ambient.onMessage("{\"event\":\"montion\", \"id\":\"kitchen\"}");
}
TEST_F(AmbientLightTest, turnOnOffWhenButtonorMontion){
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}")))
		.Times(1);
	EXPECT_CALL(arduino, milliseconds()).
			Times(AnyNumber()).
			WillRepeatedly(Return(millis));
	ambient.onMessage("{\"event\":\"button\", \"id\":\"kitchen\", \"state\":\"on\"}");
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"off\"}")))
		.Times(1);
	ambient.onMessage("{\"event\":\"button\", \"id\":\"kitchen\", \"state\":\"on\"}");
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}")))
		.Times(1);
	EXPECT_CALL(arduino, milliseconds()).
			WillOnce(Return(millis));

	ambient.onMessage("{\"event\":\"montion\", \"id\":\"kitchen\"}");
}
TEST_F(AmbientLightTest, turnOffAutomatically){
	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}")));
	EXPECT_CALL(arduino, milliseconds()).
			WillOnce(Return(millis));
	ambient.onMessage("{\"event\":\"montion\", \"id\":\"kitchen\"}");

	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"off\"}")));
	millis += TIME_DELAY + 1;
	ambient.tick(millis);
}

TEST_F(AmbientLightTest, turnOffonlyOnce){
	millis += TIME_DELAY;
	EXPECT_CALL(arduino, milliseconds()).
		WillOnce(Return(millis));

	EXPECT_CALL(router, postMessage(_, String("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}")))
		.Times(1);
	ambient.onMessage("{\"event\":\"button\", \"id\":\"kitchen\", \"state\":\"on\"}");
	ambient.tick(millis);
}
